package com.ojoin.trade.t0loan_core.web.service.impl;

import java.math.BigDecimal;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ojoin.trade.common.constdef.IConstDef;
import com.ojoin.trade.common.exception.BusinessException;
import com.ojoin.trade.common.exception.IPayNowException;
import com.ojoin.trade.common.utils.CommonUtils;
import com.ojoin.trade.common.utils.Config;
import com.ojoin.trade.common.utils.EmailSendUtil;
import com.ojoin.trade.common.utils.LogUtils;
import com.ojoin.trade.common.utils.SMSSendUtil;
import com.ojoin.trade.common.utils.TimeUtils;
import com.ojoin.trade.common.web.dao.BaseDao;
import com.ojoin.trade.common.web.domain.NotificationTemplate;
import com.ojoin.trade.common.web.domain.Result;
import com.ojoin.trade.common.web.domain.TbWeekend;
import com.ojoin.trade.common.web.domain.Result.Status;
import com.ojoin.trade.common.web.service.TbWeekEndService;
import com.ojoin.trade.common.web.service.impl.BaseServiceImpl;
import com.ojoin.trade.common.web.service.impl.NotificationTemplateService;
import com.ojoin.trade.common_core.utils.HolidayUtil;
import com.ojoin.trade.common_core.web.domain.TbMerchantInfo;
import com.ojoin.trade.common_core.web.domain.TbMerchantUser;
import com.ojoin.trade.common_core.web.domain.TbMerchantuserExceptionorder;
import com.ojoin.trade.common_core.web.domain.TbMerchantuserFinaccountVo;
import com.ojoin.trade.common_core.web.service.AccountBaseService;
import com.ojoin.trade.common_core.web.service.AdminUserBaseService;
import com.ojoin.trade.common_core.web.service.FactoringCompanyBaseService;
import com.ojoin.trade.common_core.web.service.FactoringOperatorBaseService;
import com.ojoin.trade.common_core.web.service.MerchantUserBaseService;
import com.ojoin.trade.common_core.web.service.TbMerchantInfoBaseService;
import com.ojoin.trade.common_core.web.service.TbMerchantuserExceptionorderBaseService;
import com.ojoin.trade.common_core.web.service.TbMerchantuserFinaccountService;
import com.ojoin.trade.common_core.web.service.TransferTokenStatusService;
import com.ojoin.trade.common_core.web.service.impl.DataVersionValidationService;
import com.ojoin.trade.supplyloan_core.constdef.ISLConstDef;
import com.ojoin.trade.supplyloan_core.web.domain.TbRedo;
import com.ojoin.trade.supplyloan_core.web.service.TbRedoService;
import com.ojoin.trade.t0loan_core.utils.TokenUtils;
import com.ojoin.trade.t0loan_core.web.dao.TbT0LoanFinalApplicationDao;
import com.ojoin.trade.t0loan_core.web.domain.TbFtpFile;
import com.ojoin.trade.t0loan_core.web.domain.TbT0LoanFinalApplication;
import com.ojoin.trade.t0loan_core.web.domain.TbT0LoanTransanctionLog;
import com.ojoin.trade.t0loan_core.web.domain.TbT0RefundTask;
import com.ojoin.trade.t0loan_core.web.domain.TbT0RefundTaskVO;
import com.ojoin.trade.t0loan_core.web.service.FtpFileBaseService;
import com.ojoin.trade.t0loan_core.web.service.T0LoanBaseService;
import com.ojoin.trade.t0loan_core.web.service.T0LoanFinalBaseService;
import com.ojoin.trade.t0loan_core.web.service.T0LoanTransanctionLogBaseService;
import com.ojoin.trade.t0loan_core.web.service.TbT0RefundTaskService;
import com.ojoin.weixin.core.message.model.SendMessage;

/**
 * T+0贷款基础服务实现
 * 
 * @author guoting
 * 
 */
@Service
public class T0LoanBaseServiceImpl extends
		BaseServiceImpl<TbT0LoanFinalApplication> implements T0LoanBaseService {

	@Autowired
	private TbT0LoanFinalApplicationDao dao;

	@Autowired
	private T0LoanFinalBaseService loanfinalService;

	@Autowired
	private T0LoanTransanctionLogBaseService loanlogService;

	@Autowired
	private TbMerchantInfoBaseService userinfoService;

	@Autowired
	private MerchantUserBaseService userService;

//	@Autowired
//	private PosTranscationLogBaseService poslogService;
//
//	@Autowired
//	private T0PosTranscationOfLoanTransanctionBaseService contrastService;
//
//	@Autowired
//	private T0StatusOfPosTranscationBaseService posstatusService;

	@Autowired
	private FactoringCompanyBaseService companyService;

	@Autowired
	private FactoringOperatorBaseService operService;

	@Autowired
	private AdminUserBaseService adminService;

	@Autowired
	private AccountBaseService accountService;

	@Autowired
	private TransferTokenStatusService transtokenService;

	@Autowired
	private TbT0RefundTaskService t0refundService;

	@Autowired
	private TbMerchantuserFinaccountService finaccountService;

    @Autowired
    private TbRedoService tbRedoService;
    
    @Autowired
    private FtpFileBaseService ftpService;

    @Autowired
    private TbMerchantuserExceptionorderBaseService merchantuserExceptionorderBaseService;
    
	@Autowired
	private NotificationTemplateService notificationTemplateService;

	@Autowired
	private DataVersionValidationService validateService;
	
	private long dev_amountlong = 1000000000;

	/**
	 * 放款审核(T0000015) 说明： 1)、调用新增T+0贷款业务账户变更操作日志记录(T0000011)接口，状态为未放款
	 * 2)、调用新建九盈T+0贷款记录与pos机交易记录对照表记录(T0000012)接口
	 * 3)、调用新建九盈T+0贷款记录包含的pos机交易记录状态表记录(T0000013)接口，状态为未放款未还款 以上步骤一个事务中执行
	 */
	@Override
	public void updateCreditApprove(int operatorid, int companyid,
			int joinuserid, String transdate, String operatetype, String realnetamount) throws BusinessException {
		if (IConstDef.T1_LOAN_CREDIT.equals(operatetype) || IConstDef.T0_LOAN_CREDIT.equals(operatetype)) {
			if (!isT1LoanDay())
				throw new BusinessException("今天是双休日或者是工作日中的节假日，不执行" + operatetype +"放款操作.");
		}
		
		LogUtils.getT0loanLog().info(
				"放款操作开始. " + "operatorid->" + operatorid + ", "
						+ "joinuserid->" + joinuserid + ", " + "transdate->"
						+ transdate + ", " + "operatetype->"
						+ operatetype);
		// 查询保理员对应保理公司的支付商户号
		TbT0LoanFinalApplication loanfinalvo = loanfinalService
				.queryTxLoanFinalInfoByJoinUserIDAndType(joinuserid, operatetype);
		TbMerchantInfo factor_user = userinfoService
				.queryInfoByJoinId(loanfinalvo
						.getIdOfTbMerchantUserOfCreditor());
		String factor_mhtNo = factor_user.getMhtNo();

		//TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		TbPosTranscationLog poslogSumVO = poslogService
//				.queryT1LoanPosTransInfoSumByPayUserID(joinuserid, transdate);
//		// 设置商户的放款净额为其清算金额
//		poslogSumVO.setNetamount(poslogSumVO.getClearingamount());

		TbFtpFile poslogSumVO = ftpService.selectFtpFileByJoinuseridAndTransdate(joinuserid, transdate);
		if (poslogSumVO == null)
			throw new BusinessException("pos交易合计记录为空或该笔交易已放款，请检查.");
		
		if (StringUtils.isEmpty(poslogSumVO.getClearingamount()))
			throw new BusinessException("pos交易交易合计值为空，请检查.");
		

		if (CommonUtils.getLong(realnetamount) == 0) 
			realnetamount = poslogSumVO.getClearingamount();
			
//		if (CommonUtils.getLong(realnetamount) > CommonUtils.getLong(poslogSumVO.getClearingamount()))
//			throw new BusinessException("实际放款额" + realnetamount + "大于清算金额" + poslogSumVO.getClearingamount() + "，请检查.");
		
		// 查询joinuserid对应的支付商户号
		String joinuser_mhtNo = userService.queryPayUserByJoinUserID(joinuserid);

		// 新建贷款操作日志(T0000011)
		TbT0LoanTransanctionLog logvo = new TbT0LoanTransanctionLog();
		logvo.setIdOfTbFactoringOperator(operatorid);
		logvo.setIdOfTbFactoringCompany(companyid);
		logvo.setUserIdOfIPayNowOfCreditor(factor_mhtNo);
		logvo.setUserIdOfIPayNowOfDebtor(joinuser_mhtNo);
		logvo.setIdOfTbMerchantUserOfCreditor(loanfinalvo.getIdOfTbMerchantUserOfCreditor());
		logvo.setIdOfTbMerchantUserOfDebtor(joinuserid);  
		logvo.setOperationType(operatetype);

//		logvo.setAccountBalanceOfIPayNowOfCreditor(creditAccountBalance);
		logvo.setAccountBalanceOfIPayNowOfDebtor(getAccountBalanceByMhtNo(
				joinuser_mhtNo, IConstDef.ACCTYPE_BASE));
		logvo.setIncomeFromRatio("0");
		logvo.setTransamountscale("1");
		logvo.setIncomeFromFee(poslogSumVO.getTranscost());
		logvo.setAccountTrans(poslogSumVO.getTransamount());
		logvo.setAccountClearing(poslogSumVO.getClearingamount());
		logvo.setAccountDelta(realnetamount);
		logvo.setCreditstatus(IConstDef.LOAN_APPROVED);
		logvo.setBusiDate(transdate);
		
		loanlogService.insert(logvo);
		int t0loanTransLogId = logvo.getId();

		//TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		//批量新建九盈T+0贷款记录与pos机交易记录对照表记录
//		contrastService.insertIntoT0PosTranscationOfLoanTransanction(
//				t0loanTransLogId, joinuserid, transdate);
//		
//		//批量新建九盈T+0贷款记录包含的pos机交易记录状态表记录
//		posstatusService.insertIntoPosTransStatusInfo(joinuserid, transdate);
//		
//		//批量删除已提交放款申请的pos交易记录
//		poslogService.deleteByIdInBatch(joinuserid, transdate);
		
		LogUtils.getT0loanLog().info(
				"放款审核操作结束. " + "operatorid->" + operatorid + ", "
						+ "joinuserid->" + joinuserid + ", transdate->"
						+ transdate + ", " + "operatetype->"
						+ operatetype);
	}

	private String getShouldReturnDateByOperateType(String operatetype, String busi_date) {
		if (IConstDef.T0_LOAN_CREDIT.equalsIgnoreCase(operatetype)) {
			//T0垫款商户的回款日期是T1
			return HolidayUtil.addDateByWorkDay(busi_date, 1);
		} else if (IConstDef.T1_LOAN_CREDIT.equalsIgnoreCase(operatetype)) {
			//T1垫款商户的回款日期是T2
			return HolidayUtil.addDateByWorkDay(busi_date, 2);
		} else if (IConstDef.D1_LOAN_CREDIT.equalsIgnoreCase(operatetype)) {
			//D1垫款商户的回款日期是T2
			return HolidayUtil.addDateByWorkDay(busi_date, 2);
		}
		return null;
	}

	/**
	 * 放款 说明： 1)、更新T+0贷款业务账户变更操作日志的放款状态为已放款
	 * 3)、更新九盈T+0贷款记录包含的pos机交易记录状态表记录(T0000013)接口，放款状态为已放款
	 * 4)、调用转账(JA000016)接口，从保理公司的支付账户id扣除放款金额，并为商户的支付账户id增加放款金额 以上步骤一个事务中执行
	 */
	@Override
	public void updateCreditLoan(Integer loanlogid, String operatetype, String paypwd, String pagets) throws BusinessException {
		if (loanlogid == null) {
			throw new BusinessException("待放款数据id为空，请检查.");
		}
		
		if(StringUtils.isEmpty(pagets)) {
			throw new BusinessException("上一次变更的时间为空");
		}
		
		if(StringUtils.isEmpty(paypwd)) {
			throw new BusinessException("支付密码不能为空");
		}
		
		if (IConstDef.T1_LOAN_CREDIT.equals(operatetype)) {
			if (!isT1LoanDay())
				throw new BusinessException("今天是双休日或者是工作日中的节假日，不执行" + operatetype +"放款操作.");
		}
		
		// 操作数据版本校验
		TbT0LoanTransanctionLog validateVO = new TbT0LoanTransanctionLog();
		validateVO.setId(loanlogid);
		validateService.validateVO(validateVO, pagets);
				
		LogUtils.getT0loanLog().info("===================" + operatetype + "放款操作开始. loanlogid->" + loanlogid + "===================");
		TbT0LoanTransanctionLog loanlogvo = null;
		try {
			loanlogvo = loanlogService.queryById(loanlogid);
		} catch (Exception e) {
			LogUtils.getT0loanLog().error(e.getMessage());
			throw new BusinessException("查询放款记录出错，id->" + loanlogid);
		}
		
		String creditAccountBalance = "0";
		// 查询余额修改
		if (CommonUtils.isDev()) {
			creditAccountBalance = dev_amountlong + "";
		} else {
			creditAccountBalance = getAccountBalanceByMhtNo(loanlogvo.getUserIdOfIPayNowOfCreditor(),
					IConstDef.ACCTYPE_BASE);
		}

		if (CommonUtils.getLong(creditAccountBalance) < CommonUtils
				.getLong(loanlogvo.getAccountDelta()))
			throw new BusinessException("放贷商户" + loanlogvo.getUserIdOfIPayNowOfCreditor() + "账户余额："
					+ creditAccountBalance + " 放贷金额："
					+ loanlogvo.getAccountDelta() + ", 余额不足，请充值后重试.");
			
		//TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		// 查询九盈T+0贷款记录中包含的pos机交易记录数
//		Integer poslogcount = contrastService
//				.queryT0PosTranscationCountByLoanTransanctionId(loanlogvo
//						.getId());
//		if (poslogcount == null || poslogcount.intValue() == 0) {
//			throw new BusinessException("T+0贷款记录：" + loanlogid
//					+ "包含的pos交易记录为空.");
//		}

		String debtor_mhtNo = loanlogvo.getUserIdOfIPayNowOfDebtor();
		int debtor_joinuserid = loanlogvo.getIdOfTbMerchantUserOfDebtor();
		String factor_mhtNo = loanlogvo.getUserIdOfIPayNowOfCreditor();
		String transdate = loanlogvo.getBusiDate();
		
		//TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		// 批量更新九盈T+0贷款记录包含的pos机交易记录状态表记录的放款状态
//		posstatusService.updatePosTransStatusInfoUsedByLoanStatus(debtor_joinuserid, transdate);

		String netamount = loanlogvo.getAccountDelta();
		long netamount_long = CommonUtils.getLong(loanlogvo.getAccountDelta());
		long income_from_ratio = CommonUtils.getLong(loanlogvo.getIncomeFromRatio());
		long income_from_fee = CommonUtils.getLong(loanlogvo.getIncomeFromFee());

		String transToken = TokenUtils.generateToken();
		String memo = getMemo(transToken, operatetype);

		// 更新收款商户的账户负债额、累计利率、累计手续费
		userService.updateUserBalanceAfterTransfer(debtor_joinuserid,
				income_from_ratio, income_from_fee, netamount_long, operatetype);

		// 更新放款日志状态为已放款
		Map<String, Object> parammap = new HashMap<String, Object>();
        parammap.put("id", loanlogid);
        parammap.put("creditstatus", IConstDef.LOAN_CREDITED);
        parammap.put("creditDate", TimeUtils.getCurDate());
        parammap.put("accountBalanceOfIPayNowOfCreditor", creditAccountBalance);
        parammap.put("shouldReturnDate", getShouldReturnDateByOperateType(operatetype, loanlogvo.getBusiDate()));
        parammap.put("orderId", transToken);
		loanlogService.updateT0LoanTransanctionLogVO(parammap);

		if (!CommonUtils.isDev()) {
			// 转账
//			TbMerchantUser muser = userService.queryJoinUser(factor_mhtNo);
//			String paypwd = "";
//			if (muser.getShortname().equalsIgnoreCase("QHXZ")) {
//				paypwd = Config.getProperty("szqh.paypwd");
//			} else if (muser.getShortname().equalsIgnoreCase("GHBJ")) {
//				paypwd = Config.getProperty("ghbj.paypwd");
//			} else if (muser.getShortname().equalsIgnoreCase("GHSZ")) {
//				paypwd = Config.getProperty("ghsz.paypwd");
//			}
			
			try {
				// 转账、调用不需要密码的接口 商户业务户转负债额到放款方基本户
				List rechargelist = this.accountService.rechargeAccountBalance(factor_mhtNo,
						IConstDef.ACCTYPE_BASE, paypwd, debtor_mhtNo,
						IConstDef.ACCTYPE_BASE, netamount, memo,
						transToken);
			} catch (Exception e) {
				if (e instanceof IPayNowException) {
					TbRedo redo = new TbRedo();
					redo.setApplyDate(TimeUtils.getCurDate());
					redo.setOrderId(transToken);
					Map<String, Object> map = new HashMap<>();
					map.put("loanlogid", loanlogid);
					map.put("operatetype", operatetype) ;
					map.put("paypwd", paypwd) ;
					byte[] bytes = CommonUtils.serialize(map);
					redo.setBusinessType(operatetype);
					redo.setParamstr(bytes);
					tbRedoService.insertTbRedo(redo);
					TbMerchantuserExceptionorder ordervo = new TbMerchantuserExceptionorder();
					ordervo.setOrderid(transToken);
					ordervo.setAccountStatus(IConstDef.ACCOUNT_STATUS_FREEZE);
					ordervo.setIdOfTbMerchantUser(debtor_joinuserid);
					ordervo.setBusinessType(IConstDef.EXCEPTIONORDER_TYPE_RECHARGE);
					ordervo.setOrderTime(TimeUtils.getCurDateTime());
					merchantuserExceptionorderBaseService.insertMerchantuserExceptionorder(ordervo);
				}
				throw new BusinessException(e);
			}
		}

		LogUtils.getT0loanLog().info(
				"===================" + operatetype + "放款操作结束. " + "loanlogid->" + loanlogid + ", "
						+ "joinuserid->" + debtor_joinuserid + ", " + "netamount->"
						+ netamount + "===================");
	}

	@Override
	public void updateCreditLoanRedo(int loanlogid, String operatetype, String paypwd, String orderId) throws BusinessException {
		LogUtils.getT0loanLog().info("===================" + operatetype + "放款操作开始. loanlogid->" + loanlogid + "===================");
		TbT0LoanTransanctionLog loanlogvo = null;
		try {
			loanlogvo = loanlogService.queryById(loanlogid);
		} catch (Exception e) {
			LogUtils.getT0loanLog().error(e.getMessage());
			throw new BusinessException("查询放款记录出错，id->" + loanlogid);
		}
		
		String creditAccountBalance = "0";
		// 查询余额修改
		if (CommonUtils.isDev()) {
			creditAccountBalance = dev_amountlong + "";
		} else {
			creditAccountBalance = getAccountBalanceByMhtNo(loanlogvo.getUserIdOfIPayNowOfCreditor(),
					IConstDef.ACCTYPE_BASE);
		}
		if (CommonUtils.getLong(creditAccountBalance) < CommonUtils
				.getLong(loanlogvo.getAccountDelta()))
			throw new BusinessException("放贷商户" + loanlogvo.getUserIdOfIPayNowOfCreditor() + "账户余额："
					+ creditAccountBalance + " 放贷金额："
					+ loanlogvo.getAccountDelta() + ", 余额不足，请充值后重试.");
				
		////TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		// 查询九盈T+0贷款记录中包含的pos机交易记录数
//		Integer poslogcount = contrastService
//				.queryT0PosTranscationCountByLoanTransanctionId(loanlogvo
//						.getId());
//		if (poslogcount == null || poslogcount.intValue() == 0) {
//			throw new BusinessException("T+0贷款记录：" + loanlogid
//					+ "包含的pos交易记录为空.");
//		}

		String debtor_mhtNo = loanlogvo.getUserIdOfIPayNowOfDebtor();
		int debtor_joinuserid = loanlogvo.getIdOfTbMerchantUserOfDebtor();
		String factor_mhtNo = loanlogvo.getUserIdOfIPayNowOfCreditor();
		String transdate = loanlogvo.getBusiDate();
		
		////TODO: T1、D1不记录明细信息，在ftpFile记录中记录pos交易合计值
//		// 批量更新九盈T+0贷款记录包含的pos机交易记录状态表记录的放款状态
//		posstatusService.updatePosTransStatusInfoUsedByLoanStatus(debtor_joinuserid, transdate);

		String netamount = loanlogvo.getAccountDelta();
		long clearingamount = CommonUtils.getLong(loanlogvo.getAccountClearing());
		long income_from_ratio = CommonUtils.getLong(loanlogvo.getIncomeFromRatio());
		long income_from_fee = CommonUtils.getLong(loanlogvo.getIncomeFromFee());

		String transToken = TokenUtils.generateToken();
		String memo = getMemo(transToken, operatetype);

		// 更新收款商户的账户负债额、累计利率、累计手续费
		userService.updateUserBalanceAfterTransfer(debtor_joinuserid,
				income_from_ratio, income_from_fee, clearingamount, operatetype);

		// 更新放款日志状态为已放款
		Map<String, Object> parammap = new HashMap<String, Object>();
        parammap.put("id", loanlogid);
        parammap.put("creditstatus", IConstDef.LOAN_CREDITED);
        parammap.put("creditDate", TimeUtils.getCurDate());
        parammap.put("accountBalanceOfIPayNowOfCreditor", creditAccountBalance);
        parammap.put("shouldReturnDate", getShouldReturnDateByOperateType(operatetype, loanlogvo.getBusiDate()));
        parammap.put("orderId", transToken);
		loanlogService.updateT0LoanTransanctionLogVO(parammap);

		transtokenService.updateTransferTokenStatus(orderId,IConstDef.TRANSFERSTATUS_SUCCESS,"处理成功");
        tbRedoService.updateTbRedo(orderId);
        TbMerchantuserExceptionorder ordervo=new TbMerchantuserExceptionorder();
        ordervo.setHandleTime(TimeUtils.getCurDateTime());
        ordervo.setHandleMemo("处理完毕");
        ordervo.setOrderid(orderId);
        ordervo.setAccountStatus(IConstDef.ACCOUNT_STATUS_UNFREEZE);
        merchantuserExceptionorderBaseService.updateVOByOrderId(ordervo);
        
		LogUtils.getT0loanLog().info(
				"===================" + operatetype + "放款重做操作结束. " + "loanlogid->" + loanlogid + ", "
						+ "joinuserid->" + debtor_joinuserid + ", " + "netamount->"
						+ netamount + "===================");
	}
	
//	private void insertRefundLoanTransLog(String debtor_mhtno, long returnAmount,
//			long debtorFinanceBalance, String factor_mhtNo, String transToken,
//			int operatorid, int factor_joinuserid, int debtor_joinuserid, String operation_type) throws BusinessException {
//		TbT0LoanTransanctionLog logvo = new TbT0LoanTransanctionLog();
//		logvo.setIdOfTbFactoringOperator(operatorid);
//		logvo.setIdOfTbFactoringCompany(factor_joinuserid);
//		logvo.setUserIdOfIPayNowOfCreditor(factor_mhtNo);
//		logvo.setUserIdOfIPayNowOfDebtor(debtor_mhtno);
//		logvo.setIdOfTbMerchantUserOfCreditor(factor_joinuserid);
//		logvo.setIdOfTbMerchantUserOfDebtor(debtor_joinuserid);
//		logvo.setOperationType(operation_type); // 操作类型
//		logvo.setOrderId(transToken);
//		logvo.setAccountBalanceOfIPayNowOfCreditor(getAccountBalanceByMhtNo(
//				factor_mhtNo, IConstDef.ACCTYPE_BASE));
//		logvo.setAccountBalanceOfIPayNowOfDebtor(debtorFinanceBalance + "");
//		logvo.setAccountDelta(returnAmount + "");
//		logvo.setRealReturnAmount(returnAmount + "");
//		logvo.setRealReturnDate(TimeUtils.getCurDate()); 
//		
//		if (IConstDef.T1_LOAN_RETURN.equals(operation_type)) {
//			//T+1还款操作：交易日期为前2工作日，垫款日期为前1工作日
//			logvo.setBusiDate(HolidayUtil.addDateByWorkDay(TimeUtils.getCurDate(), -2)); 
//			logvo.setCreditDate(HolidayUtil.addDateByWorkDay(TimeUtils.getCurDate(), -1)); 
//		} else if (IConstDef.D1_LOAN_RETURN.equals(operation_type)) {
//			//D+1还款操作：交易日期为前2工作日，垫款日期为交易日期后一个自然日
//			logvo.setBusiDate(HolidayUtil.addDateByWorkDay(TimeUtils.getCurDate(), -2)); 
//			try {
//				logvo.setCreditDate(TimeUtils.getDateAfterDays(logvo.getBusiDate(), 1));
//			} catch (ParseException e) {
//				throw new BusinessException(e.getMessage());
//			} 
//		} else if (IConstDef.T0_LOAN_RETURN.equals(operation_type)) {
//			//T+0还款操作：垫款日期同交易日期为前1工作日
//			logvo.setBusiDate(HolidayUtil.addDateByWorkDay(TimeUtils.getCurDate(), -1)); 
//			logvo.setBusiDate(HolidayUtil.addDateByWorkDay(TimeUtils.getCurDate(), -1)); 
//		}
//		loanlogService.insert(logvo);
//	}

	@Override
	public void updateGenRefundTask() throws BusinessException {
		List<TbMerchantuserFinaccountVo> list = finaccountService
				.queryFinaccountByType(IConstDef.TYPE_TXLOAN, IConstDef.CMBC_TYPE);
		if (CommonUtils.isEmpty(list)) {
			return;
		}
		for (TbMerchantuserFinaccountVo finaccount : list) {
			int joinid = finaccount.getIdOfTbMerchantUser();
			try {
				long accountBalance = 0;
				
				if (CommonUtils.isDev()) {
					accountBalance = dev_amountlong;
				} else {
					// 查询商户的金融户的余额
					accountBalance = accountService
							.queryFinanceAccountBanlance(finaccount.getMhtno());
				}
				// 账户余额为0不新增任务
				if (accountBalance > 0) {
					TbT0RefundTask infovo = new TbT0RefundTask();
					infovo.setIdOfTbMerchantUser(joinid);
					infovo.setAmount(CommonUtils.getString(accountBalance));
					infovo.setCurdate(TimeUtils.getCurDate());
					infovo.setState(ISLConstDef.SLREFUND_NORUN);
					t0refundService.insertT0RefundTask(infovo);

					LogUtils.getT0loanLog().info(
							"新增待还款任务成功, joinuserid->" + joinid + " amount->"
									+ accountBalance);
				}
			} catch (Exception e) {
				TbT0RefundTask infovo = new TbT0RefundTask();
				infovo.setIdOfTbMerchantUser(joinid);
				infovo.setCurdate(TimeUtils.getCurDate());
				infovo.setState(ISLConstDef.SLREFUND_QUERYFAILED);
				infovo.setMemo(e.getMessage());
				t0refundService.insertT0RefundTask(infovo);

				LogUtils.getT0loanLog().info(
						"新增待还款任务查询余额失败, joinuserid->" + joinid + " 失败原因->"
								+ e.getMessage());
			}
		}
	}

	// 查询未成功运行的还款任务，根据商户号查询业务户余额后进行还款操作
	@Override
	public void execRunRefundTask() throws BusinessException {
		List<TbT0RefundTaskVO> refundTaskList = t0refundService.queryAllUserUnsuccessRefundTask();
		if (CommonUtils.isEmpty(refundTaskList)) {
			return;
		}
		for (TbT0RefundTaskVO refundtaskvo : refundTaskList) {
			try {
				long amountlong = accountService.queryFinanceAccountBanlance(refundtaskvo.getMhtno());
				
				if (amountlong > 0) {
					String orderid = ((T0LoanBaseService) AopContext.currentProxy()).updateRunEachRefundTask(refundtaskvo);
				}
			} catch (Exception e) {
				if (e instanceof BusinessException) {
					t0refundService.updateRefundTaskStatusAndMemoById(
							refundtaskvo.getId(), IConstDef.REFUND_RUNFAILED,
							CommonUtils.getMessageByLeft1000(e.getMessage()), null);
				} else {
					t0refundService.updateRefundTaskStatusAndMemoById(
							refundtaskvo.getId(), IConstDef.REFUND_RUNFAILED,
							CommonUtils.getMessageByLeft1000(e.getMessage()), null);
				}
				continue;
			}

		}
	}

	@Override
	public void testRunRefundTask() throws BusinessException {
		List<TbT0RefundTaskVO> refundTaskList = t0refundService.queryAllUserUnsuccessRefundTask();
		if (CommonUtils.isEmpty(refundTaskList)) {
			return;
		}
		int i = 0;
		for (TbT0RefundTaskVO refundtaskvo : refundTaskList) {
			try {
				if (i == 0) {
					t0refundService.updateRefundTaskStatusAndMemoById(
							refundtaskvo.getId(), IConstDef.REFUND_RUNSUCESS,
							"运行成功", "token");
				} else {
					throw new BusinessException("error" + refundtaskvo.getId());
				}
				i++;
			} catch (Exception e) {
				if (e instanceof BusinessException) {
					t0refundService.updateRefundTaskStatusAndMemoById(
							refundtaskvo.getId(), IConstDef.REFUND_RUNFAILED,
							CommonUtils.getMessageByLeft1000(e.getMessage()), null);
				} else {
					t0refundService.updateRefundTaskStatusAndMemoById(
							refundtaskvo.getId(), IConstDef.REFUND_RUNFAILED,
							CommonUtils.getMessageByLeft1000(e.getMessage()), null);
				}
				continue;
			}

		}
	}
	
	public String updateRunEachRefundTask(TbT0RefundTaskVO refundtaskvo) throws BusinessException {
		String debtor_mhtno = refundtaskvo.getMhtno();
		TbMerchantInfo debtor_infovo = userinfoService.queryInfoByMhtno(debtor_mhtno);
		// 商户业务户余额
		long debtorFinanceBalance = accountService.queryFinanceAccountBanlance(debtor_mhtno);
		LogUtils.getT0loanLog().info("商户 " + debtor_infovo.getMchName() + "业务户余额->" + debtorFinanceBalance);
		if (debtorFinanceBalance <= 0) 
			return null;
		
		LogUtils.getT0loanLog().info("===============商户 " + debtor_mhtno + "还款开始============");

		TbMerchantUser debtor_user = userService.queryJoinUser(debtor_mhtno);
		int debtor_joinuserid = debtor_user.getId();

		// 商户负债额
		long loanbalance = CommonUtils.getLong(debtor_user.getT0LoanBalance());
		LogUtils.getT0loanLog().info("商户 " + debtor_infovo.getMchName() + "负债额->" + loanbalance);
		
		StringBuffer refundTasktransToken = new StringBuffer();

		/*************** 商户已不负债，但有回款金额，则将回款金额直接从商户的业务户全部转入基本户 **************/
		if (loanbalance == 0) {
			String transToken = TokenUtils.generateToken();
			String memo = getMemo(transToken, "transfer");

			refundTasktransToken.append(transToken);
			if (!CommonUtils.isDev()) {
				// 将回款金额直接从商户的业务户全部转入基本户
				accountService.rechargeAccountBalanceNoPwd(debtor_mhtno,
						IConstDef.ACCTYPE_FINANCING, debtor_mhtno,
						IConstDef.ACCTYPE_BASE, debtorFinanceBalance + "",
						memo, transToken);
				String msg = "商户 " + debtor_infovo.getMchName() + ", 业务户余额->" + debtorFinanceBalance + " 负债额->" + loanbalance + ", 回款金额已全部转入基本户";
				if (!CommonUtils.isDev()) {
					SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(msg));
				}
				LogUtils.getT0loanLog().info(msg);
			}
		} else {
			/*************** 商户有负债 **************/
			// 获取回款商户的债权人商户号
			TbT0LoanFinalApplication loanfinalvo = loanfinalService.queryTxLoanFinalInfoByJoinUserID(debtor_joinuserid);
			TbMerchantInfo factor_user = userinfoService.queryInfoByJoinId(loanfinalvo.getIdOfTbMerchantUserOfCreditor());
			String factor_mhtNo = factor_user.getMhtNo();

			/*************** 商户仍负债且有回款金额，
			 * 负债额>=回款金额，则从商户业务户转回款金额到放款方基本户 
			 * 负债额<回款金额，则从商户业务户转负债额到放款方基本户，再从商户业务户转回款金额-负债额到商户基本户
			 * **************/

			//查询该商户总共的垫款记录，逐步还清，更新垫款记录状态
			List<TbT0LoanTransanctionLog> unRefundTransLogList = loanlogService.queryUnRefundT0LoanTransanctionLogList(debtor_joinuserid);
			if (unRefundTransLogList == null || unRefundTransLogList.size() == 0) {
				String errormsg = "商户" + debtor_infovo.getMchName() + "负债额->" + loanbalance + "但垫款记录为空，数据不一致无法还款，请检查. ";
				if (!CommonUtils.isDev()) {
					SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(errormsg));
				}
				throw new BusinessException(errormsg);
			}
			
			//计算商户当日应还的垫款总金额
			long totalShouldRefundAmount = 0;
			for (TbT0LoanTransanctionLog loanlogvo : unRefundTransLogList) {
				totalShouldRefundAmount += CommonUtils.getLong(loanlogvo.getAccountDelta());
			}
			
			//判断商户业务户的回款金额是否大于或等于垫款金额
			if (debtorFinanceBalance >= totalShouldRefundAmount) {
				for (TbT0LoanTransanctionLog loanlogvo : unRefundTransLogList) {
					String refund_transToken = refundByTransLogVO(loanlogvo, refundtaskvo);
					if (refundTasktransToken.length() > 0)
						refundTasktransToken.append(",");
					refundTasktransToken.append(refund_transToken);
				}
			} else {
				String errormsg = "商户" + debtor_infovo.getMchName() + "今日应还款总额->" + totalShouldRefundAmount + "，回款金额->"  + debtorFinanceBalance + "，数据不一致无法还款，请检查. ";
				if (!CommonUtils.isDev()) {
					SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(errormsg));
				}
				throw new BusinessException(errormsg);
			}
			
			//判断还款后是否还有剩余金额，如有需转回商户基本户
			long rebaseAmount = debtorFinanceBalance - totalShouldRefundAmount;
			if (rebaseAmount > 0) {
				String rebase_transToken = TokenUtils.generateToken();
				String memo2 = getMemo(rebase_transToken, "transfer");
	
				if (refundTasktransToken.length() > 0)
					refundTasktransToken.append(",");
				refundTasktransToken.append(rebase_transToken);
				
				if (!CommonUtils.isDev()) {
					accountService.rechargeAccountBalanceNoPwd(
							debtor_mhtno, IConstDef.ACCTYPE_FINANCING,
							debtor_mhtno, IConstDef.ACCTYPE_BASE, rebaseAmount
									+ "", memo2, rebase_transToken);
				}
				String msg = "商户->" + debtor_infovo.getMchName() + "   还款后剩余金额:" + rebaseAmount + " 已转回商户基本户";
				SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(msg));
				LogUtils.getT0loanLog().info(msg);
			}

		}
		LogUtils.getT0loanLog().info(
				"还款操作结束. mhtname->" + refundtaskvo.getMhtname()
						+ ", mhtno->" + debtor_mhtno + ", joinuserid->"
						+ debtor_joinuserid + ", amount->"
						+ debtorFinanceBalance);

		t0refundService.updateRefundTaskStatusAndMemoById(
				refundtaskvo.getId(), IConstDef.REFUND_RUNSUCESS,
				"运行成功", refundTasktransToken.toString());
		
		TbMerchantInfo debtor_info = userinfoService.queryInfoByJoinId(refundtaskvo.getIdOfTbMerchantUser());
		if (!CommonUtils.isDev()) {
			//邮件通知
			String to=  "guoting@18join.com";
			String cc = "hgc@18join.com";
	    	// 发送内容
			BigDecimal amountdecimal = new BigDecimal(refundtaskvo.getAmount());
			String amountstr = amountdecimal.divide(new BigDecimal(100)).doubleValue()+ ""; 
			String msgcontent = "Tx还款任务执行成功，" + debtor_info.getMchName() + "金额：" + amountstr + "元";
	    	String sub = "Tx还款成功通知-" + TimeUtils.getCurDate();
	    	String from = Config.getProperty("mail.from.t1");
	    	String fromshortname = "九盈垫资业务组";
	    	LogUtils.getT0loanLog().info("正在发送邮件 收件人:{} 抄送人:{} 内容:{}", new String[] {to, cc, msgcontent});
	    	
	    	boolean isSuccess = EmailSendUtil
	    			.sendByAttchByte(from, fromshortname, to,cc, sub, msgcontent, null);
	    	
	    	if (!CommonUtils.isDev()) {
	    		//微信推送提醒信息
				SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(msgcontent));
			}
		}
		
		LogUtils.getT0loanLog().info("===============商户 " + debtor_mhtno + "还款结束============");
		
		return refundTasktransToken.toString();
	}

//	private String getCreditOperateType(TbT0RefundTaskVO refundtaskvo) {
//		String credit_operate_type = "";
//		if (IConstDef.T1_LOAN_RETURN.equals(refundtaskvo.getOperationType())) {
//			credit_operate_type = IConstDef.T1_LOAN_CREDIT;
//		} else if (IConstDef.T0_LOAN_RETURN.equals(refundtaskvo.getOperationType())) {
//			credit_operate_type = IConstDef.T0_LOAN_CREDIT;
//		} else if (IConstDef.D1_LOAN_RETURN.equals(refundtaskvo.getOperationType())) {
//			credit_operate_type = IConstDef.D1_LOAN_CREDIT;
//		}
//		return credit_operate_type;
//	}
	
	private String refundByTransLogVO(TbT0LoanTransanctionLog loanlogvo, TbT0RefundTaskVO refundtaskvo) throws BusinessException {
		TbMerchantInfo infovo = userinfoService.queryInfoByJoinId(loanlogvo.getIdOfTbMerchantUserOfDebtor());
		
		String refund_transToken = TokenUtils.generateToken();
//		String memo = getMemo(refund_transToken, loanlogvo.getOperationType() + "-还款");
		String memo = infovo.getIdOfTbMerchantUser() + "还款->" + loanlogvo.getBusiDate() + "  " + getMemo(refund_transToken, loanlogvo.getOperationType());
		long eachRefundAmount = CommonUtils.getLong(loanlogvo.getAccountDelta());
				
		// 更新放款日志状态为已还款
		Map<String, Object> parammap = new HashMap<String, Object>();
        parammap.put("id", loanlogvo.getId());
        parammap.put("creditstatus", IConstDef.LOAN_REFUNDED);
        parammap.put("realReturnDate",TimeUtils.getCurDate());
        parammap.put("realReturnAmount",eachRefundAmount);
        parammap.put("returnOrderId", refund_transToken);
		loanlogService.updateT0LoanTransanctionLogVO(parammap);
		
		// 只更新还款商户的账户负债额, 不更新累计利率、累计手续费
		String returnOperateType = getReturnOperateType(loanlogvo.getOperationType());
		userService.updateUserBalanceAfterTransfer(loanlogvo.getIdOfTbMerchantUserOfDebtor(), 0, 0, eachRefundAmount,
				returnOperateType);
		LogUtils.getT0loanLog().info("还款1->" + memo + "translogid->" + loanlogvo.getId() + ", refundamount->" + eachRefundAmount);

		if (!CommonUtils.isDev()) { // 标注：正式环境下才会调用转账接口
			try {
				LogUtils.getT0loanLog().info("还款memo->" + memo);
				// 转账、调用不需要密码的接口 商户业务户转负债额到放款方基本户
				List rechargelist = this.accountService
						.rechargeAccountBalanceNoPwd(loanlogvo.getUserIdOfIPayNowOfDebtor(), IConstDef.ACCTYPE_FINANCING,
								loanlogvo.getUserIdOfIPayNowOfCreditor(), IConstDef.ACCTYPE_BASE, eachRefundAmount + "",
								memo, refund_transToken);
				
				String msg = "商户->" + infovo.getMchName() + "   还款金额：" + eachRefundAmount + "已转回保理基本户";
				if (!CommonUtils.isDev()) {
					SendMessage.sendMsg(new String[]{"hgc","guoting"},String.format(msg));
				}
				LogUtils.getT0loanLog().info(msg);
				
			} catch (Exception e) {
				if (e instanceof IPayNowException) {
					TbRedo redo = new TbRedo();
					redo.setApplyDate(TimeUtils.getCurDate());
					redo.setOrderId(refund_transToken);
					Map<String, Object> map = new HashMap<>();
					map.put("refundtaskvo", refundtaskvo);
					byte[] bytes = CommonUtils.serialize(map);
					redo.setBusinessType(returnOperateType);
					redo.setParamstr(bytes);
					tbRedoService.insertTbRedo(redo);
					TbMerchantuserExceptionorder ordervo = new TbMerchantuserExceptionorder();
					ordervo.setOrderid(refund_transToken);
					ordervo.setAccountStatus(IConstDef.ACCOUNT_STATUS_FREEZE);
					ordervo.setIdOfTbMerchantUser(loanlogvo.getIdOfTbMerchantUserOfDebtor());
					ordervo.setBusinessType(IConstDef.EXCEPTIONORDER_TYPE_RECHARGE);
					ordervo.setOrderTime(TimeUtils.getCurDateTime());
					merchantuserExceptionorderBaseService.insertMerchantuserExceptionorder(ordervo);
				}
				throw new BusinessException(e);
			}
		}
		
		return refund_transToken;
	}

	private String getReturnOperateType(String credit_operate_type) {
		String return_operate_type = "";
		if (IConstDef.T1_LOAN_CREDIT.equals(credit_operate_type)) {
			return_operate_type = IConstDef.T1_LOAN_RETURN;
		} else if (IConstDef.T0_LOAN_CREDIT.equals(credit_operate_type)) {
			return_operate_type = IConstDef.T0_LOAN_RETURN;
		} else if (IConstDef.D1_LOAN_CREDIT.equals(credit_operate_type)) {
			return_operate_type = IConstDef.D1_LOAN_RETURN;
		}
		return return_operate_type;
	}
	
	/**
	 * 每个商户执行T1还款任务 (自动任务执行失败后重做)
	 * 
	 * 如果02的转账记录，最后确认是转账成功了，需要调用此方法进行相关记录的更新，不再调用转账
	 * 
	 * @param refundtaskvo
	 * @param orderId
	 * @throws BusinessException
	 */
	public void updateRunEachRefundRedoTask(TbT0RefundTaskVO refundtaskvo, String orderId) throws BusinessException {
		String debtor_mhtno = refundtaskvo.getMhtno();
		// 商户业务户余额
		long debtorFinanceBalance = accountService.queryFinanceAccountBanlance(debtor_mhtno);
		LogUtils.getT0loanLog().info("商户 " + debtor_mhtno + "业务户余额->" + debtorFinanceBalance);
		if (debtorFinanceBalance <= 0) {
			LogUtils.getT0loanLog().info("结束还款任务");
			return;
		}
		
		LogUtils.getT0loanLog().info("===============商户 " + debtor_mhtno + "还款开始============");

		TbMerchantUser debtor_user = userService.queryJoinUser(debtor_mhtno);
		int debtor_joinuserid = debtor_user.getId();

		// 商户负债额
		long loanbalance = CommonUtils.getLong(debtor_user.getT0LoanBalance());
		LogUtils.getT0loanLog().info("商户 " + debtor_mhtno + "负债额->" + loanbalance);
		
		StringBuffer refundTasktransToken = new StringBuffer();

		/*************** 商户已不负债，但有回款金额，则将回款金额直接从商户的业务户全部转入基本户 **************/
		if (loanbalance == 0) {
			String transToken = TokenUtils.generateToken();
			String memo = getMemo(transToken, "transfer");

			refundTasktransToken.append(transToken);
		} else {
			/*************** 商户仍负债且有回款金额，
			 * 负债额>=回款金额，则从商户业务户转回款金额到放款方基本户 
			 * 负债额<回款金额，则从商户业务户转负债额到放款方基本户，再从商户业务户转回款金额-负债额到商户基本户
			 * **************/
			long returnAmount = 0; //需还款金额
			long rebaseAmount = 0; //需转回商户基本户金额
			if (loanbalance >= debtorFinanceBalance) {
				// 商户业务户将回款金额全部转入到放款方基本户
				returnAmount = debtorFinanceBalance;
			} else {
				returnAmount = loanbalance;
				rebaseAmount = debtorFinanceBalance - loanbalance;
			}

			//查询该商户总共的垫款记录，逐步还清，更新垫款记录状态
			List<TbT0LoanTransanctionLog> unRefundTransLogList = loanlogService.queryUnRefundT0LoanTransanctionLogList(debtor_joinuserid);
			if (unRefundTransLogList != null && unRefundTransLogList.size() > 0) {
				long totalRefundAmount = 0;
				for (TbT0LoanTransanctionLog loanlogid : unRefundTransLogList) {
					String refund_transToken = TokenUtils.generateToken();
					String memo = getMemo(refund_transToken, loanlogid.getOperationType() + "-还款");
					long eachRefundAmount = CommonUtils.getLong(loanlogid.getAccountDelta());
					totalRefundAmount += eachRefundAmount;
							
					// 更新放款日志状态为已还款
					Map<String, Object> parammap = new HashMap<String, Object>();
			        parammap.put("id", loanlogid);
			        parammap.put("creditstatus", IConstDef.LOAN_REFUNDED);
			        parammap.put("realReturnDate",TimeUtils.getCurDate());
			        parammap.put("realReturnAmount",eachRefundAmount);
			        parammap.put("returnOrderId", refund_transToken);
					loanlogService.updateT0LoanTransanctionLogVO(parammap);
					
					// 只更新还款商户的账户负债额, 不更新累计利率、累计手续费
					String returnOperateType = getReturnOperateType(loanlogid.getOperationType());
					userService.updateUserBalanceAfterTransfer(debtor_joinuserid, 0, 0, eachRefundAmount,
							returnOperateType);
					LogUtils.getT0loanLog().info("还款1->" + memo + "translogid->" + loanlogid + ", refundamount->" + eachRefundAmount);
				}
				
				rebaseAmount = returnAmount - totalRefundAmount;
			}
			
		}
		LogUtils.getT0loanLog().info(
				"还款操作结束. mhtname->" + refundtaskvo.getMhtname()
						+ ", mhtno->" + debtor_mhtno + ", joinuserid->"
						+ debtor_joinuserid + ", amount->"
						+ debtorFinanceBalance);

		LogUtils.getT0loanLog().info("===============商户 " + debtor_mhtno + "还款结束============");
		
		t0refundService.updateRefundTaskStatusAndMemoById(
				refundtaskvo.getId(), IConstDef.REFUND_RUNSUCESS,
				"运行成功", refundTasktransToken.toString());
		
		TbMerchantInfo debtor_info = userinfoService.queryInfoByJoinId(refundtaskvo.getIdOfTbMerchantUser());
		if (!CommonUtils.isDev()) {
			//邮件通知
			String to=  "guoting@18join.com";
			String cc = "hgc@18join.com";
	    	// 发送内容
			BigDecimal amountdecimal = new BigDecimal(refundtaskvo.getAmount());
			String amountstr = amountdecimal.divide(new BigDecimal(100)).doubleValue()+ ""; 
	    	String msgcontent = "Tx还款任务重做执行成功，" + debtor_info.getMchName() + "还款：" + amountstr + "元已到账，请及时提现。";
	    	String sub = "Tx还款重做成功通知-" + TimeUtils.getCurDate();
	    	String from = Config.getProperty("mail.from.t1");
	    	String fromshortname = "九盈垫资业务组";
	    	LogUtils.getT0loanLog().info("正在发送邮件 收件人:{} 抄送人:{} 内容:{}", new String[] {to, cc, msgcontent});
	    	
	    	boolean isSuccess = EmailSendUtil
	    			.sendByAttchByte(from, fromshortname, to,cc, sub, msgcontent, null);
		}
		
		transtokenService.updateTransferTokenStatus(orderId,IConstDef.TRANSFERSTATUS_SUCCESS,"处理成功");
        tbRedoService.updateTbRedo(orderId);
        TbMerchantuserExceptionorder ordervo=new TbMerchantuserExceptionorder();
        ordervo.setHandleTime(TimeUtils.getCurDateTime());
        ordervo.setHandleMemo("处理完毕");
        ordervo.setOrderid(orderId);
        ordervo.setAccountStatus(IConstDef.ACCOUNT_STATUS_UNFREEZE);
        merchantuserExceptionorderBaseService.updateVOByOrderId(ordervo);
        
		LogUtils.getT0loanLog().info("===============商户 " + debtor_mhtno + "Redo还款结束============");
	}
	
	private String getMemo(String orderId, String operation_type) {
//		return getOperateTypeStr(operation_type) + ":" + orderId;
		return getOperateTypeStr(operation_type);
	}

	private String getOperateTypeStr(String operation_type) {
		String operTypeStr = "内部转账";

		if (IConstDef.T1_LOAN_CREDIT.equals(operation_type)) {
			operTypeStr = "T1垫款";
		} else if (IConstDef.T1_LOAN_RETURN.equals(operation_type)) {
			operTypeStr = "T1还款";
		} else if (IConstDef.T0_LOAN_CREDIT.equals(operation_type)) {
			operTypeStr = "T0垫款";
		} else if (IConstDef.T0_LOAN_RETURN.equals(operation_type)) {
			operTypeStr = "T0还款";
		}  else if (IConstDef.D1_LOAN_CREDIT.equals(operation_type)) {
			operTypeStr = "D1垫款";
		} else if (IConstDef.D1_LOAN_RETURN.equals(operation_type)) {
			operTypeStr = "D1还款";
		} else {
			operTypeStr = "内部转账";
		}
		return operTypeStr;
	}

	private String getAccTypeName(String acctypecode) {
		if (IConstDef.ACCTYPE_BASE.equals(acctypecode))
			return "基本户";
		else if (IConstDef.ACCTYPE_FINANCING.equals(acctypecode))
			return "余额户";

		return "未知类型账户";
	}

	@Override
	protected BaseDao<TbT0LoanFinalApplication> getBaseDao() {
		return dao;
	}
	
	/**
	 * 查询支付商户的指定账户余额
	 * 
	 * @param mhtNo
	 * @param accType
	 * @return
	 * @throws BusinessException
	 */
	private String getAccountBalanceByMhtNo(String mhtNo, String accType)
			throws BusinessException {
		if (CommonUtils.isDev())
			return CommonUtils.getString(dev_amountlong);
		
		return accountService.queryBalance(mhtNo, accType);
	}
	
	private void sendMsg(String[] placeholder, String[] placevalue,
			String type, String mobile) {
		if (CommonUtils.isEmpty(mobile))
			return;

		NotificationTemplate template = notificationTemplateService
				.findByName(type);
		if (template == null || StringUtils.isEmpty(template.getTemplate()))
			return;

		String msg = template.getTemplate();
		for (int i = 0; i < placeholder.length; i++) {
			msg = msg.replace(placeholder[i], placevalue[i]);
		}
		SMSSendUtil.sendMsg(mobile, msg);
	}
	

	/**
	 * 判断当日是否是t+1业务的放款日（双休和工作日中的节假日都不放款）
	 * 
	 * @return
	 * @throws BusinessException
	 */
	private boolean isT1LoanDay() throws BusinessException {
		GregorianCalendar calendar = new GregorianCalendar();
		TbWeekend vo = tbWeekEndService.queryWorkDayForWeekend(TimeUtils.getCurDate(), TimeUtils.getCurYear());
		// 周六、周日或者工作日中调休的节假日都不放款
		if (calendar.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.SATURDAY
				|| calendar.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.SUNDAY
				|| !CommonUtils.isEmpty(vo)) {
			return false;
		}
		return true;
	}
	
	@Autowired
	private TbWeekEndService tbWeekEndService;
	
}
